%%% File    : db_server.erl
%%% Author  :  <>
%%% Description : 
%%% Created : 24 Mar 2011 by  <>

-module(db_server).

-behaviour(gen_server).

-export([start/2]).

-export([init_tab/0,login/2]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
	terminate/2, code_change/3]).

-define(SERVER, ?MODULE).

-record(state, {sup}).

-include_lib("stdlib/include/qlc.hrl").

-record(info, {id,
	      pwd,
	      name,
	      %%state,
	      friends}).  %%[{id, name}]

%%-record(friends, {myid,
%%		 friend}).
%%-------
start(Sup, Nodes) ->
    gen_server:start({local, ?SERVER}, ?MODULE, [Sup, Nodes], []).

%%--------
init([Sup, Nodes]) ->
    process_flag(trap_exit, true),
    ok = init_db(Nodes -- [node()]),
    {ok, #state{sup=Sup}}.

handle_call({login, Id, Pwd}, _From, S) ->
    Res = login(Id, Pwd),
    {reply, Res, S};

handle_call(_Req, _From, S) ->
    {reply, ok, S}.

handle_cast({do_exit, Pid}, S=#state{sup=Sup}) ->
    case Pid =:= Sup of
	true ->
	    mnesia:stop(),
	    {stop, normal, S};
	false ->
	    {noreply, S}
    end;

handle_cast(redirect, S) ->
    redirect(S);

handle_cast(_Msg, S) ->
    {noreply, S}.

handle_info({'EXIT', _, normal}, S) ->
    {noreply, S};

handle_info({'EXIT', Pid, shutdown}, S=#state{sup=Sup}) ->
    case Pid =:= Sup of
	true ->
	    mnesia:stop(),
	    exit(normal);
	false ->
	    {noreply, S} 
    end;

handle_info({'EXIT', Pid, _Reason}, S=#state{sup=Sup}) ->
    case Pid =:= Sup of
	true ->
	   redirect(S);
	false ->
	    {noreply, S}
    end;

handle_info(_Info, S) ->
    {noreply ,S}.

terminate(_R, _S) ->
    ok.

code_change(_Oldvsn, S, _Extra) ->
    {ok, S}.


%%-----
init_db([]) -> %%the first db node
    case mnesia:create_schema([node()]) of
	ok ->
	    ok;
	{error, _Reason} ->
	    mnesia:stop(),
	    mnesia:delete_schema([node()]),
	    mnesia:create_schema([node()])
    end,
    mnesia:start(),
    init_tab(),
    ok;
init_db(Nodelist) ->
    mnesia:stop(),
    mnesia:delete_schema([node()]),
    mnesia:start(),
    mnesia:change_config(extra_db_nodes, Nodelist),
    mnesia:wait_for_tables([info], 30000),
    mnesia:change_table_copy_type(schema, node(), disc_copies),
    mnesia:add_table_copy(info, node(), disc_copies),
    %%mnesia:add_table_copy(friends, node(), disc_copies),
    ok.


init_tab() ->
    mnesia:create_table(info, [{type, set}, {disc_copies, [node()]}, {attributes, record_info(fields, info)}]),
    Fun = fun() ->
		  mnesia:write(#info{id=123, pwd="456", name="whhbest",friends = []}) end,
    mnesia:transaction(Fun).

   
redirect(S) ->
    case global:whereis_name(db_sup) of
	Pid when is_pid(Pid) ->
	    link(Pid),
	    gen_server:cast(Pid, {redirect, node(), self()}),
	    pg2:join(db, Pid),
	    {noreply, S#state{sup=Pid}};
	false ->
	    gen_server:cast(self(), redirect),
	    {noreply, S}
    end.


%%%------------db operation
login(Id, Pwd) ->
    Fun = fun() ->
		  mnesia:read({info, Id}) end,
    {atomic, Val} = mnesia:transaction(Fun),
    case Val of
	[] ->
	    {error, noexist};
	[{info, Id, Pwd, Name, Friends}] ->
	    {ok, [{Id, Name}|Friends]};
	_Others ->
	    {error, badpasswd}
    end.
